/*
 * xlogrecovery.h
 *
 * WAL 恢复和备用模式的函数
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/access/xlogrecovery.h
 */
#ifndef XLOGRECOVERY_H
#define XLOGRECOVERY_H

#include "access/xlogreader.h"
#include "catalog/pg_control.h"
#include "lib/stringinfo.h"
#include "utils/timestamp.h"

/*
 * 恢复目标类型。
 * 仅在时间点恢复期间设置，而不是在备用模式下。
 */
typedef enum
{
	RECOVERY_TARGET_UNSET,
	RECOVERY_TARGET_XID,
	RECOVERY_TARGET_TIME,
	RECOVERY_TARGET_NAME,
	RECOVERY_TARGET_LSN,
	RECOVERY_TARGET_IMMEDIATE
} RecoveryTargetType;

/*
 * 恢复目标 TimeLine 目标
 */
typedef enum
{
	RECOVERY_TARGET_TIMELINE_CONTROLFILE,
	RECOVERY_TARGET_TIMELINE_LATEST,
	RECOVERY_TARGET_TIMELINE_NUMERIC
} RecoveryTargetTimeLineGoal;

/* 恢复暂停状态 */
typedef enum RecoveryPauseState
{
	RECOVERY_NOT_PAUSED,		/* 未请求暂停 */
	RECOVERY_PAUSE_REQUESTED,	/* 已请求暂停，但尚未暂停 */
	RECOVERY_PAUSED				/* 恢复已暂停 */
} RecoveryPauseState;

/* 用户可设置的 GUC 参数 */
extern PGDLLIMPORT bool recoveryTargetInclusive;
extern PGDLLIMPORT int recoveryTargetAction;
extern PGDLLIMPORT int recovery_min_apply_delay;
extern PGDLLIMPORT char *PrimaryConnInfo;
extern PGDLLIMPORT char *PrimarySlotName;
extern PGDLLIMPORT char *recoveryRestoreCommand;
extern PGDLLIMPORT char *recoveryEndCommand;
extern PGDLLIMPORT char *archiveCleanupCommand;

/* 通过 GUC 系统间接设置 */
extern PGDLLIMPORT TransactionId recoveryTargetXid;
extern PGDLLIMPORT char *recovery_target_time_string;
extern PGDLLIMPORT TimestampTz recoveryTargetTime;
extern PGDLLIMPORT const char *recoveryTargetName;
extern PGDLLIMPORT XLogRecPtr recoveryTargetLSN;
extern PGDLLIMPORT RecoveryTargetType recoveryTarget;
extern PGDLLIMPORT char *PromoteTriggerFile;
extern PGDLLIMPORT bool wal_receiver_create_temp_slot;
extern PGDLLIMPORT RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal;
extern PGDLLIMPORT TimeLineID recoveryTargetTLIRequested;
extern PGDLLIMPORT TimeLineID recoveryTargetTLI;

/* 我们是否已经达到了一个一致的数据库状态？ */
extern PGDLLIMPORT bool reachedConsistency;

/* 我们目前是否处于备用模式？ */
extern PGDLLIMPORT bool StandbyMode;

extern Size XLogRecoveryShmemSize(void);
extern void XLogRecoveryShmemInit(void);

extern void InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdownPtr, bool *haveBackupLabel, bool *haveTblspcMap);
extern void PerformWalRecovery(void);

/*
 * FinishWalRecovery() 返回这个。它包含恢复结束时的点
 * 和结束原因的信息。
 */
typedef struct
{
	/*
	 * 有关最后有效或应用记录的信息，之后可以追加新的WAL。
	 * 'lastRec'是最后记录开始的位置，'endOfLog'是它的结束。
	 * 'lastPage'是最后部分页面的副本，包含endOfLog（如果endOfLog恰好在
	 * 页面边界，则为NULL）。'lastPageBeginPtr'是最后页面开始的位置。
	 *
	 * endOfLogTLI是包含最后应用记录的XLOG段文件名中的TLI。
	 * 如果在该段中发生了时间线切换，并且我们正在从属于更高时间线的段中读取旧WAL，
	 * 则它可能与lastRecTLI不同。
	 */
	XLogRecPtr	lastRec;		/* 最后有效或应用记录的开始 */
	TimeLineID	lastRecTLI;
	XLogRecPtr	endOfLog;		/* 最后有效或应用记录的结束 */
	TimeLineID	endOfLogTLI;

	XLogRecPtr	lastPageBeginPtr;	/* 包含endOfLog的页面的LSN */
	char	   *lastPage;		/* 到endOfLog的最后页面的副本 */

	/*
	 * abortedRecPtr是恢复完成时WAL末尾破损记录的起始指针；
	 * missingContrecPtr是第一个丢失的对抗记录的位置。详见CreateOverwriteContrecordRecord。
	 */
	XLogRecPtr	abortedRecPtr;
	XLogRecPtr	missingContrecPtr;

	/* 短的可读字符串，描述恢复结束的原因 */
	char	   *recoveryStopReason;

	/*
	 * 如果找到了备用或恢复信号文件，则相应地设置这些标志。
	 */
	bool		standby_signal_file_found;
	bool		recovery_signal_file_found;
} EndOfWalRecoveryInfo;

extern EndOfWalRecoveryInfo *FinishWalRecovery(void);
extern void ShutdownWalRecovery(void);
extern void RemovePromoteSignalFiles(void);

extern bool HotStandbyActive(void);
extern XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI);
extern RecoveryPauseState GetRecoveryPauseState(void);
extern void SetRecoveryPause(bool recoveryPause);
extern void GetXLogReceiptTime(TimestampTz *rtime, bool *fromStream);
extern TimestampTz GetLatestXTime(void);
extern TimestampTz GetCurrentChunkReplayStartTime(void);
extern XLogRecPtr GetCurrentReplayRecPtr(TimeLineID *replayEndTLI);

extern bool PromoteIsTriggered(void);
extern bool CheckPromoteSignal(void);
extern void WakeupRecovery(void);

extern void StartupRequestWalReceiverRestart(void);
extern void XLogRequestWalReceiverReply(void);

extern void RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue);

extern void xlog_outdesc(StringInfo buf, XLogReaderState *record);

#endif							/* XLOGRECOVERY_H */
